<template>
  <div class="main-container flex-col bg-white m-[20px]">
    <div class="mx-4 pt-4">
      <div class="top-container flex justify-between border-b-2 pb-4">
        <div class="flex">
          <div class="prefix-icon"></div>
          <span class="ml-2 text-base font-semibold">异动基金</span>
        </div>
        <div class="">
          <template v-for="(item, index) in Frequency" :key="index">
            <el-button
              :class="{ 'is-active': selectItem === item }"
              @click="selectFrequency(item)"
              >{{ item }}</el-button
            >
          </template>
        </div>
      </div>
      <div class="flex">
        <div class="left-container my-2 mr-2 flex-col w-1/2 items-stretch">
          <div>
            <span class="text-sm font-semibold text-blue-600"
              >{{ singleFrequency }}异动基金<span class="px-1 text-red-500">{{ total }}</span
              >只</span
            >
          </div>
          <div class="mt-2 text-sm bg-gray-100">
            <div class="flex items-center whitespace-nowrap">
              <span class="text-black px-2">净值异动</span>
              <el-checkbox-group v-model="netValSelectedList" class="flex">
                <el-checkbox
                  v-for="(value, key) in NetValAbnormalLabelLookup"
                  :key="key"
                  :value="key"
                  style="margin-right: 5px"
                  :class="String(key).includes('涨') ? 'idx-up' : 'idx-down'"
                  >{{ key }}</el-checkbox
                >
              </el-checkbox-group>
            </div>
            <div class="flex items-center whitespace-nowrap">
              <span class="text-black px-2">久期异动</span>
              <el-checkbox-group v-model="durationSelectedList" class="flex">
                <el-checkbox
                  v-for="(value, key) in DurationLabelLookup"
                  :key="key"
                  :value="key"
                  style="margin-right: 5px"
                  :class="String(key).includes('涨') ? 'idx-up' : 'idx-down'"
                  >{{ key }}</el-checkbox
                >
              </el-checkbox-group>
            </div>
            <div class="flex items-center whitespace-nowrap">
              <span class="text-black px-2">其他异动</span>
              <el-checkbox-group v-model="otherSelectedList" class="flex">
                <el-checkbox
                  v-for="(value, key) in Object.entries(AbormalTypeLookup).filter(
                    ([key]) => key !== '净值异动' && key !== '久期异动',
                  )"
                  :key="key"
                  :value="value[1]"
                  style="margin-right: 5px"
                  :class="setOtherAbnormalBackground(value[1])"
                  >{{ value[0] }}</el-checkbox
                >
              </el-checkbox-group>
            </div>
          </div>
          <div class="my-5">
            <el-table
              max-height="500"
              :data="tableData"
              stripe
              style="width: 100%"
              class="customer-table"
              highlight-current-row
              @current-change="sendRowInfo2Right"
              :header-row-class-name="'custom-header'"
            >
              <el-table-column label="基金名称" prop="sIrdName"></el-table-column>
              <el-table-column label="基金类型" prop="cmfType"></el-table-column>
              <el-table-column label="异动日期" prop="alertDt" sortable>
                <template #default="scope">
                  {{ dateFormat(scope.row.alertDt, 'YYYY-MM-DD') }}
                </template>
              </el-table-column>
              <el-table-column label="日涨跌幅" prop="navPchg" sortable>
                <template #default="scope">
                  <span :class="0 > scope.row.navPchg ? 'text-green-600' : 'text-red-500'">{{
                    scope.row.navPchg ? scope.row.navPchg.toFixed(2) + '%' : '--'
                  }}</span>
                </template>
              </el-table-column>
              <el-table-column label="异动类型" prop="alertLabel">
                <template #default="scope">
                  <span
                    v-html="
                      scope.row.alertLabel
                        .split(',')
                        .map((label: string) => {
                          if (label.includes('涨')) {
                            return `<span class='text-red-500'>${label}</span>`
                          } else if (label.includes('跌')) {
                            return `<span class='text-green-600'>${label}</span>`
                          } else if (label.includes('久期')) {
                            return `<span class='text-blue-600'>${label}</span>`
                          } else if (label.includes('信用')) {
                            return `<span class='text-yellow-400'>${label}</span>`
                          } else if (label.includes('舆情')) {
                            return `<span class='text-purple-500'>${label}</span>`
                          } else {
                            return `<span>${label}</span>`
                          }
                        })
                        .join('、')
                    "
                  ></span>
                </template>
              </el-table-column>
            </el-table>
            <div style="display: flex; justify-content: end; margin-top: 16px">
              <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="currentPage"
                :page-sizes="[10, 20, 50, 100]"
                :page-size="pageSize"
                layout="total, prev, pager, next, sizes"
                :total="total"
              >
              </el-pagination>
            </div>
          </div>
        </div>
        <div
          class="right-container pt-2 pl-5 w-1/2 flex-col bg-gradient-to-r from-slate-100 via-white via-5% to-white"
        >
          <div class="h-1/2">
            <div class="flex justify-between items-center">
              <span class="text-sm font-semibold text-blue-600"
                >{{ singleFrequency }}净值异动<span class="px-1 text-red-500">{{
                  netValAbnormalNum
                }}</span
                >次</span
              >
              <el-select v-model="netValIdxSelected" value-key="benchCode" style="width: 300px">
                <el-option
                  v-for="item in netValBenchList"
                  :key="item.benchCode"
                  :value="item"
                  :label="item.benchName"
                ></el-option>
              </el-select>
            </div>
            <v-chart :option="netValOption" autoresize></v-chart>
          </div>
          <div class="h-1/2 my-3">
            <div class="flex justify-between items-center">
              <span class="text-sm font-semibold text-blue-600"
                >{{ singleFrequency }}久期异动<span class="px-1 text-red-500">{{
                  durationAbnormalNum
                }}</span
                >次</span
              >
              <el-select v-model="durationIdxSelected" value-key="benchCode" style="width: 300px">
                <el-option
                  v-for="item in durationBenchList"
                  :key="item.benchCode"
                  :value="item"
                  :label="item.benchName"
                ></el-option>
              </el-select>
            </div>
            <v-chart :option="durationOption" autoresize></v-chart>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue'
import {
  Frequency,
  NetValAbnormalLabelLookup,
  AbormalTypeLookup,
  DurationLabelLookup,
} from './enums'
import type {
  AbnormalFundInfo,
  AbnormalInfo,
  AlertParam,
  BenchInfo,
  DurationAbnormalInfo,
} from './types'
import { getW1055056, getW1055057, getW1055058, getW1055059, getW1055060 } from '@/api/fundalert.js'
import { dateFormat } from '@/utils/dateUtils'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
import {
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  LegendComponent,
} from 'echarts/components'
import VChart from 'vue-echarts'

use([
  TooltipComponent,
  CanvasRenderer,
  GridComponent,
  DataZoomComponent,
  LineChart,
  LegendComponent,
])

const singleFrequency = ref('近三月')
const netValAbnormalNum = ref(0)
const durationAbnormalNum = ref(0)
const netValSelectedList = ref([])
const durationSelectedList = ref([])
const otherSelectedList = ref([])
//构建筛选类型入参
const alertParams = computed(() => {
  const alerts: AlertParam[] = []
  if (0 < netValSelectedList.value.length) {
    alerts.push({
      alertType: 1,
      alertLabel: [...netValSelectedList.value],
    })
  }
  if (0 < durationSelectedList.value.length) {
    alerts.push({
      alertType: 2,
      alertLabel: [...durationSelectedList.value],
    })
  }
  if (0 < otherSelectedList.value.length) {
    otherSelectedList.value.forEach((single) => {
      alerts.push({
        alertType: single,
        alertLabel: [],
      })
    })
  }
  return alerts
})

const selectItem = ref('近三月')
const selectFrequency = (item: string) => {
  selectItem.value = item
  singleFrequency.value = item
  currentPage.value = 1
  pageSize.value = 10
  invokerW1055056()
}

watch(alertParams, (newVal, oldVal) => {
  if (newVal !== oldVal) {
    invokerW1055056()
  }
})

const setOtherAbnormalBackground = (value: string) => {
  if ('2' === value) {
    return 'bg-sky-50'
  }
  if ('3' === value) {
    return 'bg-orange-50'
  }
  if ('4' === value) {
    return 'bg-pink-50'
  }
}
/**左边表格相关逻辑 */
const tableData = ref<AbnormalFundInfo[]>([])
onMounted(async () => {
  invokerW1055056() //左边table渲染
})
const invokerW1055056 = async () => {
  const params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
    begin: getDateRange(singleFrequency.value)[0],
    end: getDateRange(singleFrequency.value)[1],
    alertParams: alertParams.value,
  }
  const res = await getW1055056(params)
  if (res?.data?.records) {
    total.value = res.data.total
    tableData.value = res.data.records

    netValBenchList.value = await invokerW105560('债券指数') //净值异动idxList 渲染
    netValIdxSelected.value = netValBenchList.value[0]
    durationBenchList.value = await invokerW105560('') //久期异动idxList 渲染
    durationIdxSelected.value = durationBenchList.value[0]
    //调用查询接口后立即请求时序图
    const single: AbnormalFundInfo = tableData.value[0]
    sendRowInfo2Right(single)
  }
}
const pageSize = ref(10)
const handleSizeChange = (val: number) => {
  currentPage.value = 1 //重置到第一页
  pageSize.value = val
  invokerW1055056()
}
const handleCurrentChange = (val: number) => {
  currentPage.value = val
  invokerW1055056()
}
const total = ref(0)

const currentPage = ref(1)

const getDateRange = (dateFrequence: string) => {
  const today = new Date()

  switch (dateFrequence) {
    case Frequency.YESTER_DAY:
      const yesterday = new Date(today)
      yesterday.setDate(today.getDate() - 1)
      return [dateFormat(yesterday), dateFormat(yesterday)]
    case Frequency.ONE_MONTH:
      const monthBegin = new Date(today)
      monthBegin.setDate(today.getDate() - 30)
      return [dateFormat(monthBegin), dateFormat(today)]
    case Frequency.THREE_MONTH:
      const threeBegin = new Date(today)
      threeBegin.setMonth(today.getMonth() - 3)
      return [dateFormat(threeBegin), dateFormat(today)]
    case Frequency.HALF_YEAR:
      const halfBegin = new Date(today)
      halfBegin.setDate(today.getDate() - 180)
      return [dateFormat(halfBegin), dateFormat(today)]
    case Frequency.ONE_YEAR:
      const oneBegin = new Date(today)
      oneBegin.setDate(today.getDate() - 360)
      return [dateFormat(oneBegin), dateFormat(today)]
    default:
      return ['', '']
  }
}

//从基金详情跳转时序图（净值及久期）
const sendRowInfo2Right = (val: AbnormalFundInfo) => {
  sIrdcode.value = val?.sIrdcode
  sIrdName.value = val?.sIrdName
  invokerW1055058() //净值异动时序图
  invokerW1055059() //久期异动时序图
}

//右边时序图相关逻辑
const netValueSeq = ref<AbnormalInfo[]>([])
const durationSeq = ref<DurationAbnormalInfo[]>([])
//默认基准code 800收益
const netValBenchCode = computed(() => netValIdxSelected.value?.benchCode)

const sIrdcode = ref('159837.SZ')
const sIrdName = ref('')

const invokerW1055058 = async () => {
  const params = {
    benchCode: netValBenchCode.value,
    sIrdcode: sIrdcode.value, //'159837.SZ',
    begin: getDateRange(singleFrequency.value)[0],
    end: getDateRange(singleFrequency.value)[1],
  }
  const res = await getW1055058(params)
  if (res?.data?.netWorthVos) {
    netValueSeq.value = res.data.netWorthVos
    netValAbnormalNum.value = res.data.eventQuantity
  }
}

const durationBenchCode = computed(() => durationIdxSelected.value?.benchCode)
const invokerW1055059 = async () => {
  const params = {
    benchCode: durationBenchCode.value,
    sIrdcode: sIrdcode.value, //'000085.OF', //
    begin: getDateRange(singleFrequency.value)[0],
    end: getDateRange(singleFrequency.value)[1],
  }
  const res = await getW1055059(params)
  if (res?.data?.prolongedVos) {
    durationSeq.value = res.data.prolongedVos
    durationAbnormalNum.value = res.data.eventQuantity
  }
}
const netValBenchList = ref<BenchInfo[]>([])
const durationBenchList = ref<BenchInfo[]>([])
const invokerW105560 = async (val?: string) => {
  const params = {
    benchType1: val || '',
    searchContent: '',
  }
  const res = await getW1055060(params)
  if (res?.data) {
    return res?.data
  }
}

const netValIdxSelected = ref<BenchInfo>()
const durationIdxSelected = ref<BenchInfo>()

//vue3-chart
import markPointIcon from '@/assets/img/markpoint.svg?url'

const abnormalOption = (seq, fundName: string, benchName?: string) => ({
  tooltip: {
    trigger: 'axis',
    position: function (pos, params, dom, rect, size) {
      // 鼠标在左侧时 tooltip 显示到右侧，鼠标在右侧时 tooltip 显示到左侧。
      const obj = { top: 60 }
      obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 5
      return obj
    },
    formatter: function (params) {
      const date = seq[params[0].dataIndex].date
      const eventVos = seq[params[0].dataIndex].eventVos
      return `
        <div style="font-size: 14px; padding: 4px;">
          <div style="color: #666;">${date}</div>
          ${params
            .map(
              (param) => `
            <div style="margin-top: 4px;">
              ${param.marker}
              <span style="color: #000000 65%">${param.seriesName}</span>
              <span style="color: #000000 65%">${param.value ? param.value.toFixed(2) + '%' : '--'}</span>
            </div>
            `,
            )
            .join('')}
          ${
            eventVos?.length > 0
              ? eventVos
                  .map(
                    (event) => `
              <div style="margin-top: 4px;">
                <span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color: ${Number(event.strangeIndexValue) >= 0 ? '#f5222d' : '#7cc448'};"></span>
                <span style="color: #000000 65%;">${event.alertLabel}：</span>
                <span style="color: ${Number(event.strangeIndexValue) >= 0 ? '#f5222d' : '#52c41a'}; font-weight: bold;">
                  ${event.strangeIndexValue ? Number(event.strangeIndexValue).toFixed(2) +  '%' : '--'}
                </span>
              </div>`,
                  )
                  .join('')
              : ``
          }
        </div>
      `
    },
  },
  legend: {
    show: 'true',
    orient: 'horizontal',
    x: 'center',
    y: 'bottom',
    padding: 1,
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    axisLabel: {
      rotate: 15,
      textStyle: {
        color: '#54657e',
        //align: 'center',
      },
    },
    axisLine: {
      lineStyle: {
        color: '#CAD3DF',
      },
    },
    data: seq.map((single) => single.date),
  },
  yAxis: {
    type: 'value',
    axisLine: {
      show: false, // Hides y-axis line
    },
    name: '',
    boundaryGap: [0, '10%'],
    splitLine: {
      show: true,
      lineStyle: {
        type: 'dashed',
      },
    },
  },
  dataZoom: [
    {
      type: 'inside',
      height: 20,
      start: 90,
      end: 100,
    },
    {
      type: 'slider',
      height: 20,
      start: 0,
      end: 10,
      showDetail: false,
    },
  ],
  grid: {
    left: '5%',
    right: '2%',
    bottom: '12%',
    top: '10%',
    containLabel: true,
    show: true,
    borderWidth: 0,
    backgroundColor: '#f5f9ff',
  },
  series: [
    {
      name: fundName,
      type: 'line',
      symbol: 'none',
      large: false, // 关闭优化
      showAllSymbol: true,
      sampling: 'lttb',
      itemStyle: {
        color: '#1890ff',
      },
      data: seq.map((single) => {
        return 0 < single.eventVos?.length
          ? {
              value: single.navAdj ? single.navAdj * 100 : single.prdDuration,
              symbol: `image://${markPointIcon}`,
              symbolSize: [15, 15],
              symbolKeepAspect: true,
              symbolOffset: [0, 0],
            }
          : single.navAdj
            ? single.navAdj * 100
            : single.prdDuration
      }),
    },
    {
      name: benchName,
      type: 'line',
      symbol: 'none',
      sampling: 'lttb',
      itemStyle: {
        color: '#ff9900',
      },
      data: seq.map((single) =>
        single.benchmarkDailyReturn ? (single.benchmarkDailyReturn * 100) : single.avgMvDuration,
      ),
    },
  ],
})

const saveDigital = (val: number, digital?: number) => {
  return val ? (val * 100).toFixed(digital ? digital : 2) : 0.0
}

//净值异动seq变动触发时序图渲染
const netValOption = ref()
watch(netValueSeq, (newVal, oldVal) => {
  if (oldVal !== newVal) {
    netValOption.value = abnormalOption(
      netValueSeq.value,
      sIrdName.value,
      netValIdxSelected.value?.benchName,
    )
  }
})
watch(netValIdxSelected, (newVal, oldVal) => {
  if (oldVal?.benchCode && oldVal?.benchCode !== newVal?.benchCode) {
    invokerW1055058()
  }
})
//久期异动seq变动触发时序图渲染
const durationOption = ref()
watch(durationSeq, (newVal, oldVal) => {
  if (oldVal !== newVal) {
    durationOption.value = abnormalOption(
      durationSeq.value,
      sIrdName.value,
      durationIdxSelected.value?.benchName,
    )
  }
})
watch(durationIdxSelected, (newVal, oldVal) => {
  if (oldVal?.benchCode && oldVal?.benchCode !== newVal?.benchCode) {
    invokerW1055059()
  }
})
</script>

<style lang="scss" scoped>
.main-container {
  .prefix-icon {
    width: 6px;
    height: 19px;
    background: #2468f2;
    border-radius: 3px;
  }
  :deep(.el-button + .el-button) {
    margin-left: 0px;
  }
  .left-container {
    .idx-up {
      :deep(
        .el-checkbox__input.is-checked .el-checkbox__inner,
        .el-checkbox__input.is-indeterminate .el-checkbox__inner
      ) {
        border-color: #fe5d58 !important;
        background-color: #fe5d58 !important;
      }
      :deep(.el-checkbox__input.is-focus .el-checkbox__inner) {
        border-color: #fe5d58 !important;
      }
      //修改选中后文本的颜色
      :deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
        color: #fe5d58 !important;
      }
    }
    .idx-down {
      :deep(
        .el-checkbox__input.is-checked .el-checkbox__inner,
        .el-checkbox__input.is-indeterminate .el-checkbox__inner
      ) {
        border-color: #209442 !important;
        background-color: #209442 !important;
      }
      :deep(.el-checkbox__input.is-focus .el-checkbox__inner) {
        border-color: #209442 !important;
      }
      //修改选中后文本的颜色
      :deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
        color: #209442 !important;
      }
    }
    .customer-table :deep(.custom-header) th {
      background-color: #f3f5fb;
      font-weight: 350;
    }
  }

  .right-container {
    .chart {
      height: 100vh;
    }
  }
}
</style>
